package pl.edu.pw.elka.jtrzasko.proz.warcaby.model;

import java.util.Iterator;
import java.util.LinkedList;

import pl.edu.pw.elka.jtrzasko.proz.warcaby.figures.Figure;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.figures.FigureColor;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.figures.Pawn;

/**
 * Klasa przechowuje informacje o planszy na ktorej toczy sie gra. Zawiera
 * kolekcje figur dostepnych na planszy
 */
public class Board {
	public static final int LINE_MAX = 8;
	private LinkedList<Figure> figures;

	/**
	 * Utowrzenie nowej pustej planszy
	 */
	public Board() {
		figures = new LinkedList<Figure>();
	}

	/**
	 * Ustawienie na planszy pinkow na pozycjach domyslnych przy rozpoczeciu gry
	 */
	public void setupFigures(FigureColor color, int startLine, int endLine) {
		for (int i = startLine; i <= endLine; i++)
			for (int j = 0; j < LINE_MAX; j++)
				if ((i + j) % 2 == 1)
					figures.add(new Pawn(new Position(i, j), color));
	}


	/**
	 * Sprawdza czy dane pole jest puste
	 * 
	 * @param p
	 *            Pole ktore sprawdzmy
	 * @return Prawda jesli pole jest puste
	 */
	public boolean isFieldEmpty(Position p) {
		return getFigure(p) == null ? true : false;
	}

	/**
	 * Skasowanie figury z danego pola
	 * 
	 * @param p
	 *            Pole z ktorego ma byc skasowana figura
	 */
	private void setFieldEmpty(Position p) {
		Iterator<Figure> i = figures.iterator();
		while (i.hasNext()) {
			if (i.next().getPosition().equals(p))
				i.remove();
		}
	}

	/**
	 * Ustawienie danych figury na danym folu
	 * 
	 * @param figure
	 *            Figura do wstawienia
	 */
	public void setFigureOnField(Figure figure) {
		setFieldEmpty(figure.getPosition());
		figures.add(figure);
	}

	/**
	 * Zamiana miejscami pola pustego z polem zawierajacym figure
	 * 
	 * @param p1
	 *            Pierwsze pole
	 * @param p2
	 *            Drugie pole
	 */
	public void swapFields(Position p1, Position p2) {
		if (getFigure(p1) == null)
			getFigure(p2).setPosition(p1);
		if (getFigure(p2) == null)
			getFigure(p1).setPosition(p2);

	}

	/**
	 * Sprawdza czy na planszy sa jakies biale figury
	 * 
	 * @return Prawda, jesli na planszy istnieje przynajmniej jedna biala
	 *         figura.
	 */
	public boolean isAnyFigure(FigureColor color) {
		Iterator<Figure> i = figures.iterator();
		while (i.hasNext())
			if (i.next().getColor() == color)
				return true;
		return false;
	}

	/**
	 * Pobiera figure stojaca na wskazanym polu
	 * 
	 * @param p
	 *            Pole na ktorym stoi szukana figura
	 * @return Znleziona figura
	 */
	public Figure getFigure(Position p) {
		Iterator<Figure> i = figures.iterator();
		while (i.hasNext()) {
			Figure tmp = i.next();
			if (tmp.getPosition().equals(p))
				return tmp;
		}
		return null;
	}

	/**
	 * Usuwa wszytkie figury z danych pozycji
	 * 
	 * @param positions
	 *            Zestaw pol plaszy, ktory ma zaostac wyczyszczony
	 */
	public void removeFigures(Position[] positions) {
		for (Position p : positions)
			setFieldEmpty(p);
	}

	/**
	 * Sprawdza czy na danych polach znajduje sie figura o wskzanym kolorze
	 * 
	 * @param positions
	 *            Zestaw pol do sprawdzenia
	 * @param color
	 *            Szukany kolor
	 * @return Prawda jesli w zbiorze pol znajduje sie przynajmniej jedna figura
	 *         o danym kolorze
	 */
	public boolean isFieldsContainsColor(Position[] positions, FigureColor color) {
		for (Position p : positions)
			if (!isFieldEmpty(p) && getFigure(p).getColor() == color)
				return true;
		return false;
	}

	/**
	 * Sprawdza czy na sasiednich polach znajduja sie swie figury obok siebie
	 * 
	 * @param positions
	 *            Zestaw pol do sprawdzenia
	 * @return Prawda jesli w zbiorze pol znajduja sie dwie figury obok siebie
	 */
	public boolean isFieldsContainsDoubleFigure(Position[] positions) {

		int doubleCounter = 0;
		for (Position p : positions) {
			if (!isFieldEmpty(p))
				doubleCounter++;
			else
				doubleCounter = 0;
			if (doubleCounter == 2)
				return true;
		}
		return false;
	}

	/**
	 * Sprawdza czy na dane pola sa puste
	 * 
	 * @param positions
	 *            Zestaw pol do sprawdzenia
	 * @return Prawda jesli w pola nie zawieraja zadnej fugiry
	 */
	public boolean isFieldsEmpty(Position[] positions) {
		for (Position p : positions)
			if (!isFieldEmpty(p))
				return false;
		return true;
	}

	/**
	 * Przsygotowuje zestaw informacji o figurach znajdujacych sie na planszy
	 * 
	 * @return Zestaw informacjo o figurach znajdujacy sie na planszy
	 */
	public LinkedList<Figure> getFigures() {
		LinkedList<Figure> positionSet = new LinkedList<Figure>();
		Iterator<Figure> i = figures.iterator();
		while (i.hasNext())
			positionSet.add(i.next());
		return positionSet;
	}
	
}
